package com.plat.api.api.action;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo;
import cn.binarywang.wx.miniapp.bean.WxMaUserInfo;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.ReUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSONObject;
import com.plat.api.anonation.NoToken;
import com.plat.api.anonation.Token;
import com.plat.api.api.action.service.PlatTokenService;
import com.plat.api.common.RedisKey;
import com.plat.api.common.RespCode;
import com.plat.api.dao.api.TokenDao;
import com.plat.api.dao.api.UserDao;
import com.plat.api.entity.api.TokenEntity;
import com.plat.api.entity.api.UserEntity;
import com.plat.api.exception.PlatException;
import com.plat.api.redis.RedisCache;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import org.beetl.sql.core.query.LambdaQuery;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;

/**
 * Created with IntelliJ IDEA.
 * User: shish
 * Date: 2020/5/9
 * Time: 21:39
 * Description: No Description
 */
@Service
@Slf4j
@Token
public class LoginAction {
    @Autowired
    private UserDao userDao;
    @Autowired
    private TokenDao tokenDao;
    @Autowired
    private WxMaService wxMaService;
    @Autowired
    private PlatTokenService tokenService;
    @Autowired
    private RedisCache redisCache;

    @NoToken
    public JSONObject getPhoneNumber(JSONObject jsonObject) throws WxErrorException {
        JSONObject body = jsonObject.getJSONObject("body");
        JSONObject json = new JSONObject();
        //String sessionKey, String encryptedData, String ivStr
        WxMaJscode2SessionResult  wxMaJscode2SessionResult = wxMaService.jsCode2SessionInfo(body.getString("code"));
        String sessionKey  =wxMaJscode2SessionResult.getSessionKey();
        String encryptedData  =body.getString("encryptedData");
        String iv  =body.getString("iv");
        WxMaPhoneNumberInfo wxMaPhoneNumberInfo =  wxMaService.getUserService().getPhoneNoInfo(sessionKey,encryptedData,iv);
        json.put("object",wxMaPhoneNumberInfo);
        return json;
    }
    @NoToken
    public JSONObject login(JSONObject jsonObject) {
        JSONObject body = jsonObject.getJSONObject("body");
        String code = body.getString("code");
        String phone = body.getString("phone");
        String email = body.getString("email");
        String password = body.getString("password");
        String iv = body.getJSONObject("uersInfo").getString("iv");
        String checkCode = body.getString("checkCode");
        String encryptedData = body.getJSONObject("uersInfo").getString("encryptedData");
        String token = "";
        if (code != null) {
            WxMaUserInfo userInfo = null;
            WxMaJscode2SessionResult wxMaJscode2SessionResult = null;
            try {
                wxMaJscode2SessionResult = wxMaService.jsCode2SessionInfo(code);
                //wxMaService.getAccessToken();
                // String json = getUserInfo(wxMaService.getAccessToken(),wxMaJscode2SessionResult.getOpenid());
                userInfo = wxMaService.getUserService().getUserInfo(wxMaJscode2SessionResult.getSessionKey(), encryptedData, iv);
                //String json =  WeChatUtil.getUserInfo(encryptedData,wxMaJscode2SessionResult.getSessionKey(),iv);
//                JSONObject jsonObject1 = JSONObject.parseObject(json);
//                userInfo = JSONObject.toJavaObject(jsonObject1,WxMaUserInfo.class);
            } catch (Exception e) {
                e.printStackTrace();
                log.info("登录发生错误" + e.getMessage());
                throw new PlatException(RespCode.WX_AUTH_ERROR.getCode(), RespCode.WX_AUTH_ERROR.getError_msg());
            }
            UserEntity userEntity = userDao.getUserInfo(userInfo.getOpenId());
            if (userEntity != null) {
                token = tokenService.createToken(userEntity.getId());
            } else {
                userEntity = new UserEntity();
                userEntity.setName(userInfo.getNickName());
                userEntity.setGender(Integer.valueOf(userInfo.getGender()));
                userEntity.setNowAddress(userInfo.getCountry() + "." + userInfo.getProvince() + "." + userInfo.getCity());
                userEntity.setField("未知领域");
                userEntity.setHasAuth(0);
                userEntity.setHasEdit(0);
                userEntity.setOpenId(userInfo.getOpenId());
                userEntity.setCreateTime(new Date());
                userEntity.setWxHeadPhoto(userInfo.getAvatarUrl());
                userEntity.setUserInfo(userInfo.toString());
                String account = RandomUtil.randomNumbers(4)+" "+RandomUtil.randomNumbers(3)+" "+RandomUtil.randomNumbers(3)+" "+RandomUtil.randomNumbers(3)+" "+RandomUtil.randomNumbers(3)+" "+RandomUtil.randomNumbers(4);
                userEntity.setAccount(account);
                userDao.insert(userEntity);
                //生成token
                token = tokenService.createToken(userEntity.getId());
            }
        } else {
            UserEntity userEntity = userDao.getUserInfo(email, phone, password);
            if (userEntity != null) {
                if (!redisCache.hasKey(RedisKey.checkKey + checkCode)) {
                    throw new PlatException(RespCode.CHECK_CODE_ERROR.getCode(), RespCode.CHECK_CODE_ERROR.getError_msg());
                } else {
                    String cacheObject = redisCache.getCacheObject(RedisKey.checkKey + checkCode);
                    if (checkCode.equals(cacheObject)) {
                        token = tokenService.createToken(userEntity.getId());
                    } else {
                        throw new PlatException(RespCode.CHECK_CODE_ERROR.getCode(), RespCode.CHECK_CODE_ERROR.getError_msg());
                    }
                }
            } else {
                throw new PlatException(RespCode.LOGIN_ERROR.getCode(), RespCode.LOGIN_ERROR.getError_msg());
            }
        }
        JSONObject json = new JSONObject();
        LambdaQuery<TokenEntity> query = tokenDao.getSQLManager().lambdaQuery(TokenEntity.class);
        TokenEntity tokenEntity = query.andEq("token", token).single();
        UserEntity userEntity = userDao.getSQLManager().lambdaQuery(UserEntity.class).andEq("id", tokenEntity.getUserId()).single();
        json.put("token", token);
        json.put("user", userEntity);
        return json;
    }

    @NoToken
    public JSONObject register(JSONObject jsonObject) {
        JSONObject body = jsonObject.getJSONObject("body");
        String phoneOremail = body.getString("phoneOremail");
        String pwd = body.getString("password");
        String rePwd = body.getString("rePassword");
        String code = body.getString("code");
        UserEntity userEntity = new UserEntity();
        if (!pwd.equals(rePwd)) {
            throw new PlatException(RespCode.PASSWORD_ERROR.getCode(), RespCode.PASSWORD_ERROR.getError_msg());
        }
        String t1 = "[^0-9]*[1][3-9][0-9]{9}[^0-9].*";
        String t2 = "^\\s*\\w+(?:\\.{0,1}[\\w-]+)*@[a-zA-Z0-9]+(?:[-.][a-zA-Z0-9]+)*\\.[a-zA-Z]+\\s*$";
        if (!redisCache.hasKey(RedisKey.checkKey + code)) {
            throw new PlatException(RespCode.CHECK_CODE_ERROR.getCode(), RespCode.CHECK_CODE_ERROR.getError_msg());
        } else {
            String cacheObject = redisCache.getCacheObject(RedisKey.checkKey + code);
            if (code.equals(cacheObject)) {
                if (ReUtil.isMatch(t1, phoneOremail) && !ReUtil.isMatch(t2, phoneOremail)) {
                    userEntity.setPhone(phoneOremail);
                } else if (!ReUtil.isMatch(t1, phoneOremail) && !ReUtil.isMatch(t2, phoneOremail)) {
                    userEntity.setEmail(phoneOremail);
                } else {
                    throw new PlatException(RespCode.PHONE_OR_EMAIL_ERROR.getCode(), RespCode.PHONE_OR_EMAIL_ERROR.getError_msg());
                }
            } else {
                throw new PlatException(RespCode.CHECK_CODE_ERROR.getCode(), RespCode.CHECK_CODE_ERROR.getError_msg());
            }
        }
        userEntity.setPassword(pwd);
        userDao.insert(userEntity);
        String token = tokenService.createToken(userEntity.getId());
        JSONObject json = new JSONObject();
        json.put("token", token);
        return json;
    }

    @NoToken
    public JSONObject updateUser(JSONObject jsonObject) {
        JSONObject body = jsonObject.getJSONObject("body");
        String code = body.getString("code");
        String token = jsonObject.getJSONObject("head").getString("token");
        String iv = body.getString("iv");
        String encryptedData = body.getString("encryptedData");
        WxMaUserInfo userInfo = null;
        WxMaJscode2SessionResult wxMaJscode2SessionResult = null;
        try {
            wxMaJscode2SessionResult = wxMaService.jsCode2SessionInfo(code);
            userInfo = wxMaService.getUserService().getUserInfo(wxMaJscode2SessionResult.getSessionKey(), encryptedData, iv);
        } catch (Exception e) {
            e.printStackTrace();
            log.info("登录发生错误" + e.getMessage());
            throw new PlatException(RespCode.WX_AUTH_ERROR.getCode(), RespCode.WX_AUTH_ERROR.getError_msg());
        }
        TokenEntity tokenEntity = tokenDao.getSQLManager().lambdaQuery(TokenEntity.class).andEq("token", token).single();
        UserEntity userEntity = userDao.unique(tokenEntity.getUserId());
        userEntity.setOpenId(userInfo.getOpenId());
        userEntity.setWxHeadPhoto(userInfo.getAvatarUrl());
        userEntity.setNickname(userInfo.getNickName());
        userDao.updateById(userEntity);
        JSONObject json = new JSONObject();
        json.put("token", token);
        return json;
    }

    public JSONObject update(JSONObject jsonObject) {
        JSONObject body = jsonObject.getJSONObject("body");
        String token = jsonObject.getJSONObject("head").getString("token");
        String field = body.getString("field");
        Integer age = body.getInteger("age");
        String userName = body.getString("userName");
        String email = body.getString("email");
        String password = body.getString("password");
        String phone = body.getString("phone");
        String nowAddress = body.getString("name");
        String gender = body.getString("gender");
        TokenEntity tokenEntity = tokenDao.getSQLManager().lambdaQuery(TokenEntity.class).andEq("token", token).single();
        UserEntity userEntity = userDao.getSQLManager().lambdaQuery(UserEntity.class).andEq("id", tokenEntity.getUserId()).single();
        userEntity.setId(tokenEntity.getUserId());
        userEntity.setField(field);
        userEntity.setNowAddress(nowAddress);
        userEntity.setPhone(phone);
        userEntity.setName(userName);
        userEntity.setEmail(email);
        if (gender.equals("男")) {
            userEntity.setGender(1);
        }
        if (gender.equals("女")) {
            userEntity.setGender(2);
        }
        if (gender.equals("未知性别")) {
            userEntity.setGender(0);
        }
        userEntity.setAge(age);
        userEntity.setHasEdit(1);
        userDao.updateById(userEntity);
        jsonObject = new JSONObject();
        jsonObject.put("object", userEntity);
        return jsonObject;
    }

    /**
     * 得到微信用户信息
     *
     * @param accessToken
     * @param openId
     * @return
     */
    public String getUserInfo(String accessToken, String openId) {
        // 拼接请求地址
        String requestUrl = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN";
        requestUrl = requestUrl.replace("ACCESS_TOKEN", accessToken).replace(
                "OPENID", openId);
        // 获取用户信息
        String jsonObject = HttpUtil.get(requestUrl);
        return jsonObject;
    }
}
